﻿using System;
using System.Reactive;

namespace WcfDynamicProxy
{
    /// <summary>
    /// Extensions for RX
    /// </summary>
    public static class ReactiveExtensions
    {
       
        /// <summary>
        /// Осуществляет подписку на IObservable, c передавчей синхронных ошибок в канал он error
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="onNext"></param>
        /// <param name="catchAll"></param>
        /// <param name="completed"></param>
        /// <returns></returns>
        public static IDisposable SubscribeSafe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> catchAll, Action completed)
        {
            return source.SubscribeSafe(
                Observer.Create(
                    onNext,
                    catchAll,
                    completed));
        }

        /// <summary>
        /// Осуществляет подписку на IObservable, c передавчей синхронных ошибок в канал он error
        /// Действие по OnCompleted - Nop
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="onNext"></param>
        /// <param name="catchAll"></param>
        /// <returns></returns>
        public static IDisposable SubscribeSafe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> catchAll)
        {
            return source.SubscribeSafe(onNext, catchAll, Stubs.Nop);
        }

        /// <summary>                
        /// Осуществляет подписку на IObservable, c передавчей синхронных ошибок в канал он error
        /// События OnError "Глотаются" !!!!! Внимание это существенное отличние от обыного Subscribe где в качестве обрабочкиа OnError используется Stub.Throw
        /// Действие по OnCompleted - Nop
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="onNext"></param>
        /// <returns></returns>
        public static IDisposable SubscribeSafe<T>(this IObservable<T> source, Action<T> onNext)
        {
            return source.SubscribeSafe(onNext, Stubs.Swallow);
        }

        public static IDisposable SubscribeSafe<T>(this IObservable<T> source)
        {
            return source.SubscribeSafe(Stubs<T>.Ignore);
        }


        private static class Stubs
        {
            /// <summary>
            /// "Глотание" ошибки
            /// </summary>
            public static readonly Action<Exception> Swallow = ex => { };

            /// <summary>
            /// Пустая операция
            /// </summary>
            public static readonly Action Nop = () => { };
        }

        private static class Stubs<T>
        {
            /// <summary>
            /// Пустая операция
            /// </summary>
            public static readonly Action<T> Ignore = _ => { };
        }
    }
}
